<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>lodash Test Suite</title>
    <link rel="stylesheet" href="../node_modules/qunitjs/qunit/qunit.css">
    <style>
      #exports, #module {
        display: none;
      }
    </style>
  </head>
  <body>
    <script>
      // Avoid reporting tests to Sauce Labs when script errors occur.
      if (location.port == '9001') {
        window.onerror = function(message) {
          if (window.QUnit) {
            QUnit.config.done.length = 0;
          }
          global_test_results = { 'message': message };
        };
      }
    </script>
    <script src="../node_modules/lodash/lodash.js"></script>
    <script>var lodashStable = _.noConflict();</script>
    <script src="../node_modules/qunitjs/qunit/qunit.js"></script>
    <script src="../node_modules/qunit-extras/qunit-extras.js"></script>
    <script src="../node_modules/platform/platform.js"></script>
    <script src="./asset/test-ui.js"></script>
    <div id="qunit"></div>
    <div id="exports"></div>
    <div id="module"></div>
    <script>
      function setProperty(object, key, value) {
        try {
          Object.defineProperty(object, key, {
            'configurable': true,
            'enumerable': false,
            'writable': true,
            'value': value
          });
        } catch (e) {
          object[key] = value;
        }
        return object;
      }

      function addBizarroMethods() {
        var funcProto = Function.prototype,
            objectProto = Object.prototype;

        var hasOwnProperty = objectProto.hasOwnProperty,
            fnToString = funcProto.toString,
            nativeString = fnToString.call(objectProto.toString),
            noop = function() {},
            propertyIsEnumerable = objectProto.propertyIsEnumerable,
            reToString = /toString/g;

        function constant(value) {
          return function() {
            return value;
          };
        }

        function createToString(funcName) {
          return constant(nativeString.replace(reToString, funcName));
        }

        // Allow bypassing native checks.
        setProperty(funcProto, 'toString', (function() {
          function wrapper() {
            setProperty(funcProto, 'toString', fnToString);
            var result = hasOwnProperty.call(this, 'toString') ? this.toString() : fnToString.call(this);
            setProperty(funcProto, 'toString', wrapper);
            return result;
          }
          return wrapper;
        }()));

        // Add prototype extensions.
        funcProto._method = noop;

        // Set bad shims.
        setProperty(Object, '_create', Object.create);
        setProperty(Object, 'create', (function() {
          function object() {}
          return function(prototype) {
            if (prototype === Object(prototype)) {
              object.prototype = prototype;
              var result = new object;
              object.prototype = undefined;
            }
            return result || {};
          };
        }()));

        setProperty(Object, '_getOwnPropertySymbols', Object.getOwnPropertySymbols);
        setProperty(Object, 'getOwnPropertySymbols', undefined);

        setProperty(objectProto, '_propertyIsEnumerable', propertyIsEnumerable);
        setProperty(objectProto, 'propertyIsEnumerable', function(key) {
          return !(key == 'valueOf' && this && this.valueOf === 1) && _propertyIsEnumerable.call(this, key);
        });

        setProperty(window, '_Map', window.Map);
        if (_Map) {
          setProperty(window, 'Map', (function(Map) {
            var count = 0;
            return function() {
              if (count++) {
                return new Map;
              }
              var result = {};
              setProperty(window, 'Map', Map);
              return result;
            };
          }(_Map)));

          setProperty(Map, 'toString', createToString('Map'));
        }
        setProperty(window, '_Promise', window.Promise);
        setProperty(window, 'Promise', noop);

        setProperty(window, '_Set', window.Set);
        setProperty(window, 'Set', noop);

        setProperty(window, '_Symbol', window.Symbol);
        setProperty(window, 'Symbol', undefined);

        setProperty(window, '_WeakMap', window.WeakMap);
        setProperty(window, 'WeakMap', noop);

        // Fake `WinRTError`.
        setProperty(window, 'WinRTError', Error);

        // Fake free variable `global`.
        setProperty(window, 'exports', window);
        setProperty(window, 'global', window);
        setProperty(window, 'module', {});
      }

      function removeBizarroMethods() {
        var funcProto = Function.prototype,
            objectProto = Object.prototype;

        setProperty(objectProto, 'propertyIsEnumerable', objectProto._propertyIsEnumerable);

        if (Object._create) {
          Object.create = Object._create;
        } else {
          delete Object.create;
        }
        if (Object._getOwnPropertySymbols) {
          Object.getOwnPropertySymbols = Object._getOwnPropertySymbols;
        } else {
          delete Object.getOwnPropertySymbols;
        }
        if (_Map) {
          Map = _Map;
        } else {
          setProperty(window, 'Map', undefined);
        }
        if (_Promise) {
          Promise = _Promise;
        } else {
          setProperty(window, 'Promise', undefined);
        }
        if (_Set) {
          Set = _Set;
        } else {
          setProperty(window, 'Set', undefined);
        }
        if (_Symbol) {
          Symbol = _Symbol;
        }
        if (_WeakMap) {
          WeakMap = _WeakMap;
        } else {
          setProperty(window, 'WeakMap', undefined);
        }
        setProperty(window, '_Map', undefined);
        setProperty(window, '_Promise', undefined);
        setProperty(window, '_Set', undefined);
        setProperty(window, '_Symbol', undefined);
        setProperty(window, '_WeakMap', undefined);

        setProperty(window, 'WinRTError', undefined);

        setProperty(window, 'exports', document.getElementById('exports'));
        setProperty(window, 'global', undefined);
        setProperty(window, 'module', document.getElementById('module'));

        delete funcProto._method;
        delete Object._create;
        delete Object._getOwnPropertySymbols;
        delete objectProto._propertyIsEnumerable;
      }

      // Load lodash to expose it to the bad extensions/shims.
      if (!ui.isModularize) {
        addBizarroMethods();
        document.write('<script src="' + ui.buildPath + '"><\/script>');
      }
    </script>
    <script>
      // Store lodash to test for bad extensions/shims.
      if (!ui.isModularize) {
        var lodashBizarro = window._;
        window._ = undefined;
        removeBizarroMethods();
      }
      // Load test scripts.
      document.write((ui.isForeign || ui.urlParams.loader == 'none')
        ? '<script src="' + ui.buildPath + '"><\/script><script src="test.js"><\/script>'
        : '<script data-dojo-config="async:1" src="' + ui.loaderPath + '"><\/script>'
      );
    </script>
    <script>
      var lodashModule,
          shimmedModule,
          underscoreModule;

      (function() {
        if (window.curl) {
          curl.config({ 'apiName': 'require' });
        }
        if (ui.isForeign || !window.require) {
          return;
        }
        var reBasename = /[\w.-]+$/,
            basePath = ('//' + location.host + location.pathname.replace(reBasename, '')).replace(/\btest\/$/, ''),
            modulePath = ui.buildPath.replace(/\.js$/, ''),
            moduleMain = modulePath.match(reBasename)[0],
            locationPath = modulePath.replace(reBasename, '').replace(/^\/|\/$/g, ''),
            shimmedLocationPath = './abc/../' + locationPath,
            underscoreLocationPath = './xyz/../' + locationPath,
            uid = +new Date;

        function getConfig() {
          var result = {
            'baseUrl': './',
            'urlArgs': 't=' + uid++,
            'waitSeconds': 0,
            'paths': {},
            'packages': [{
              'name': 'test',
              'location': basePath + 'test',
              'main': 'test',
              'config': {
                // Work around no global being exported.
                'exports': 'QUnit',
                'loader': 'curl/loader/legacy'
              }
            }],
            'shim': {
              'shimmed': {
                'exports': '_'
              }
            }
          };

          if (ui.isModularize) {
            result.packages.push({
              'name': 'lodash',
              'location': locationPath,
              'main': moduleMain
            }, {
              'name': 'shimmed',
              'location': shimmedLocationPath,
              'main': moduleMain
            }, {
              'name': 'underscore',
              'location': underscoreLocationPath,
              'main': moduleMain
            });
          } else {
            result.paths.lodash = modulePath;
            result.paths.shimmed = shimmedLocationPath + '/' + moduleMain;
            result.paths.underscore = underscoreLocationPath + '/' + moduleMain;
          }
          return result;
        }

        function loadTests() {
          require(getConfig(), ['test'], function() {
            QUnit.start();
          });
        }

        function loadModulesAndTests() {
          require(getConfig(), ['lodash', 'shimmed', 'underscore'], function(lodash, shimmed, underscore) {
            lodashModule = lodash;
            lodashModule.moduleName = 'lodash';

            if (shimmed) {
              shimmedModule = shimmed.result(shimmed, 'noConflict') || shimmed;
              shimmedModule.moduleName = 'shimmed';
            }
            if (underscore) {
              underscoreModule = underscore.result(underscore, 'noConflict') || underscore;
              underscoreModule.moduleName = 'underscore';
            }
            window._ = lodash;

            if (ui.isModularize) {
              require(getConfig(), [
                'lodash/_baseEach',
                'lodash/_isIndex',
                'lodash/_isIterateeCall'
              ], function(baseEach, isIndex, isIterateeCall) {
                lodash._baseEach = baseEach;
                lodash._isIndex = isIndex;
                lodash._isIterateeCall = isIterateeCall;
                loadTests();
              });
            } else {
              loadTests();
            }
          });
        }

        QUnit.config.autostart = false;

        if (window.requirejs) {
          addBizarroMethods();
          require(getConfig(), ['lodash'], function(lodash) {
            lodashBizarro = lodash.result(lodash, 'noConflict') || lodash;
            delete requirejs.s.contexts._;

            removeBizarroMethods();
            loadModulesAndTests();
          });
        } else {
          loadModulesAndTests();
        }
      }());

      // Set a more readable browser name.
      window.onload = function() {
        var timeoutId = setInterval(function() {
          var ua = document.getElementById('qunit-userAgent');
          if (ua) {
            ua.innerHTML = platform;
            clearInterval(timeoutId);
          }
        }, 16);
      };
    </script>
  </body>
</html>
